package uk.ac.aber.paws.server.stats;

import java.util.*;
import java.util.logging.Level;
import java.io.*;
import javax.naming.directory.SearchControls;
import uk.ac.aber.paws.server.config.ConfigManager;
import uk.ac.aber.paws.server.core.PAWSServer;
import uk.ac.aber.paws.server.db.*;
import uk.ac.aber.paws.server.ldap.LDAPQuery;
import uk.ac.aber.paws.server.util.Mailer;

/**
 * @author Rob Johnson, Aberystwyth University
 * @email rob.johnson@aber.ac.uk
 * @date 21st May 2012
 * 
 * GenerateLiveComputerStats.java
 * 
 * A utility class used by Aberystwyth University for exported xml detailing the
 * live public workstation usage at the university. It needs rewriting at some
 * point to make better use of teh new stored procedures.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class GenerateLiveComputerStats {

	
	private static Vector<String> FAULTY_COMPUTER_LIST = new Vector<String>();
	private static String[] FAULTY_COMPUTER_LIST_RECIPS = ConfigManager.getProperty("app.mailer.faulty.recips").split(";");
	
	private static boolean checkProcessed = false;

	public static void runMe() {
		
		Hashtable<String,String> dataHash = new Hashtable<String,String>();
		
		dataHash.put("GENERATED_TIME",new Date(Calendar.getInstance().getTimeInMillis()).toString());
		
		boolean timeTrigger = false;
		
		try {
			
			FAULTY_COMPUTER_LIST = new Vector<String>();
			
			Calendar currentDate = Calendar.getInstance();
			
			// only send the email at 7am on a Monday morning each week....
			if (currentDate.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY && currentDate.get(Calendar.HOUR_OF_DAY) == 7 && !checkProcessed) {

				timeTrigger = true;
			}
				
			// reset the flag back to false when we get to 8am so that next Monday will allow the check email to be sent again
			if (currentDate.get(Calendar.HOUR_OF_DAY) == 8) {
				checkProcessed = false;
			}

			// only update status within the hours of 6am - 8pm
			if (currentDate.get(Calendar.HOUR_OF_DAY) > 6 && currentDate.get(Calendar.HOUR_OF_DAY) < 20) {
				
				generateXMLoutput(dataHash);
			}
			
			if (timeTrigger) {
			//	sendFaultyComputerListMail(currentDate);
				timeTrigger = false;
				checkProcessed = true;
			}
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}
	
	private static void generateXMLoutput(Hashtable<String,String> dataHash) {
		
		try { 
			
			Vector<Hashtable<String,Object>> MONITOR_ROOM_GROUPINGS = (new DBLogger()).getRoomGroupings();
			
			StringBuffer enXML = new StringBuffer();
			StringBuffer cyXML = new StringBuffer();
			
			enXML.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
			cyXML.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
			
			enXML.append("<psvstats>\n");
			cyXML.append("<psvstats>\n");
			
			enXML.append("<lastupdated>"+(String)dataHash.get("GENERATED_TIME")+"</lastupdated>\n");
			cyXML.append("<lastupdated>"+(String)dataHash.get("GENERATED_TIME")+"</lastupdated>\n");
			
			enXML.append("<buildings>\n");
			cyXML.append("<buildings>\n");
			
			// for each room grouping
			for (int i=0;i<MONITOR_ROOM_GROUPINGS.size();i++) {
				
				Hashtable<String,Object> groupHash = MONITOR_ROOM_GROUPINGS.get(i);
				
				enXML.append("\t<building>\n");
				cyXML.append("\t<building>\n");
				
				enXML.append("\t\t<buildingname>"+groupHash.get("GroupingLabel1")+"</buildingname>\n");
				cyXML.append("\t\t<buildingname>"+groupHash.get("GroupingLabel2")+"</buildingname>\n");
				
				enXML.append("\t\t<buildingimage>"+groupHash.get("ImagePath")+"</buildingimage>\n");
				cyXML.append("\t\t<buildingimage>"+groupHash.get("ImagePath")+"</buildingimage>\n");
				
				enXML.append("\t\t<rooms>\n");
				cyXML.append("\t\t<rooms>\n");
				
				Hashtable<String,String> MONITOR_ROOM_LIST_EN = (new DBLogger()).getRoomStatsList((String)groupHash.get("GroupingKey"),false);
				Hashtable<String,String> MONITOR_ROOM_LIST_CY = (new DBLogger()).getRoomStatsList((String)groupHash.get("GroupingKey"),true);
				
				// english
				Enumeration<String> keys = MONITOR_ROOM_LIST_EN.keys();
				Enumeration<String> cykeys = MONITOR_ROOM_LIST_CY.keys();
				
				while (keys.hasMoreElements()) {
				
					enXML.append("\t\t\t<room>\n");
					cyXML.append("\t\t\t<room>\n");
				
					String ou = keys.nextElement();
					enXML.append("\t\t\t\t<roomname>"+MONITOR_ROOM_LIST_EN.get(ou)+"</roomname>\n");
					cyXML.append("\t\t\t\t<roomname>"+MONITOR_ROOM_LIST_CY.get(ou)+"</roomname>\n");
				
					String domainName = "."+LDAPQuery.convertToFQDN(ou,false).toLowerCase();
					
					Vector<String> tmpVector = LDAPQuery.ouLookup(ConfigManager.getProperty("app.ldap.loginserver"+domainName),ConfigManager.getProperty("app.ldap.protocol"+domainName),ConfigManager.getProperty("app.ldap.port"+domainName),ConfigManager.getProperty("app.ldap.username"+domainName),ConfigManager.getProperty("app.ldap.password"+domainName),ConfigManager.getProperty("app.ldap.logindomain"+domainName),true,ConfigManager.getProperty("app.ldap.method"+domainName), ou, "computer", SearchControls.ONELEVEL_SCOPE);
					
			    	int inUse = 0;
			    	
			    	for (int j=0;j<tmpVector.size();j++) {
			    		if (((new DBLogger()).isUserLoggedIn(LDAPQuery.convertToFQDN((String)tmpVector.get(j),true)))) {
			    			inUse++;
			    		}
			    	}
			       
			    	enXML.append("\t\t\t\t<total>"+tmpVector.size()+"</total>\n");
			    	enXML.append("\t\t\t\t<available>"+(tmpVector.size()-inUse)+"</available>\n");
			    	cyXML.append("\t\t\t\t<total>"+tmpVector.size()+"</total>\n");
			    	cyXML.append("\t\t\t\t<available>"+(tmpVector.size()-inUse)+"</available>\n");
			    	
			    	float percentUse = ((float)inUse/tmpVector.size())*100.0f;
			    	enXML.append("\t\t\t\t<percentUsage>"+percentUse+"</percentUsage>\n");
			    	cyXML.append("\t\t\t\t<percentUsage>"+percentUse+"</percentUsage>\n");
			    
			    	if (percentUse >= 0 && percentUse < 60) {
			    		enXML.append("\t\t\t\t<divbar>savingsbar-green</divbar>\n");
			    		cyXML.append("\t\t\t\t<divbar>savingsbar-green</divbar>\n");
			    	}
			    	else if (percentUse >= 60 && percentUse < 90) {
			    		enXML.append("\t\t\t\t<divbar>savingsbar-orange</divbar>\n");
			    		cyXML.append("\t\t\t\t<divbar>savingsbar-orange</divbar>\n");
			    	}
			    	else if (percentUse >= 90 && percentUse < 100) {
			    		enXML.append("\t\t\t\t<divbar>savingsbar-red</divbar>\n");
			    		cyXML.append("\t\t\t\t<divbar>savingsbar-red</divbar>\n");			    		
			    	}
			    	else {
			    		enXML.append("\t\t\t\t<divbar>savingsbar-black</divbar>\n");
			    		cyXML.append("\t\t\t\t<divbar>savingsbar-black</divbar>\n");
			    	}
			    	
					enXML.append("\t\t\t</room>\n");
					cyXML.append("\t\t\t</room>\n");
				}
					
				enXML.append("\t\t</rooms>\n");
				cyXML.append("\t\t</rooms>\n");
				
				enXML.append("\t</building>\n");
				cyXML.append("\t</building>\n");
			}
			
			enXML.append("</buildings>\n");
			cyXML.append("</buildings>\n");

			enXML.append("</psvstats>\n");
			cyXML.append("</psvstats>\n");
			
			BufferedWriter enBW = new BufferedWriter(new FileWriter(ConfigManager.getProperty("app.stats.webdir.base")+ConfigManager.getProperty("app.stats.webdir.psvstats.xml.en")));
			BufferedWriter cyBW= new BufferedWriter(new FileWriter(ConfigManager.getProperty("app.stats.webdir.base")+ConfigManager.getProperty("app.stats.webdir.psvstats.xml.cy")));
			
			enBW.write(enXML.toString());
			cyBW.write(cyXML.toString());
			
			enBW.close();
			cyBW.close();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		
	}
	
	private static void sendFaultyComputerListMail(Calendar currentDate) {
	
		String messageBody = "";
		
		messageBody += "The following PSV workstations have been identified as inactive due to no successful user logins within the last 14 days.\n\n";
		messageBody += "This will require action, as detailed in the action plan at the bottom of this email.\n\n";
		
		
		for (int i=0;i<FAULTY_COMPUTER_LIST.size();i++) {
		
			String computer = (String)FAULTY_COMPUTER_LIST.get(i);

			//messageBody += "Room: "+LDAPQuery.resolveComputerOU(computer,"psv.aber.ac.uk","psv")+"  Computer: "+computer+"\n";
			
		}
		
		messageBody += "\n\nACTION PLAN\n\n";
		messageBody += "It is possible that a computer has simply not been used for a long time. This is possible in quiet computer rooms. Some computers may have been turned off at the wall which discourages other users from using it. The operators are required to log calls based off the following action plan:\n\n";
		messageBody += "1) Check that the computer is pingable. If so, then report as a \"WMI Fault\" via Sunrise to DTS Software Team.\n";
		messageBody += "2) Check that the computer is pingable. If not, then report as a \"Connection Fault\" via Sunrise to the Workshop Team.\n";
		messageBody += "3) You should generally get a feel for which computers are heavily used and which are not. Some safe assumptions can be made off this basis.\n\n";
		
		try {
			PAWSServer.LOG_FILE.log(Level.ALL,"printing psv fault distribution email...");
			Mailer.postMail(FAULTY_COMPUTER_LIST_RECIPS,"PSV Workstation Weekly Fault Report",messageBody,ConfigManager.getProperty("app.mail.mailsender"));
		}
		catch (Exception ex) {	
			ex.printStackTrace();
		}
	}

	
		
}
